// Copyright (C) 2000 BotS Q3 Team
//

/*****************************************************************************
 * name:		bots_local.h
 *
 * desc:		Quake3 Battle of the Sexes General Include file
 *
 * $Archive: /source/code/game/bots_local.h $
 * $Author: tbp $ 
 * $Revision: 1.3 $
 * $Modtime: 1/15/00 2:04a $
 * $Date: 2001/01/08 05:24:02 $
 *
 *****************************************************************************/
#ifndef __G_BOTS_LOCAL_H__
#define __G_BOTS_LOCAL_H__


// Weapon damage values
#define BOTS_BFG_DAMAGE					250
#define BOTS_RAILGUN_DAMAGE				85
#define BOTS_SHOTGUN_DAMAGE				10
#define BOTS_STINGER_DAMAGE				5
#define BOTS_MACHINEGUN_DAMAGE			8
#define BOTS_GRENADELAUNCHER_DAMAGE		100
#define BOTS_HAND_GRENADE_DAMAGE		100
#define BOTS_ROCKETLAUNCHER_DAMAGE		100
#define BOTS_PLASMA_DAMAGE				15
#define BOTS_GAUNTLET_DAMAGE			100
#define BOTS_LIGHTNING_DAMAGE			9 //tbp: toned it down a bit (was 13)
#define BOTS_GRAPPLE_DAMAGE				50


// Map modes
#define	FLAG_CAPTURES	1
#define	CAPTURE_PADS	2


#define BOTS_PACK_AMMO		100
#define BOTS_PACK_ARMOR		100

#define BOTS_MAX_TEAMS		2
#define BOTS_MAX_CLASSES	9
#define BOTS_MAX_KEYS		2
#define BOTS_MAX_LEVEL		4

#define TEAM_HEALTH_PROTECT			1		// No health damage from friendly fire
#define TEAM_ARMOR_PROTECT			2		// No armor damage from friendly fire
#define TEAM_ATTACKER_DAMAGE		4		// Attacker takes damage from hitting teammates
#define TEAM_FRAG_PENALTY			8		// One frag penalty for killing teammate
#define TEAM_DEATH_PENALTY          16		// Die when you kill a teammate.
#define TEAM_KEEPTEAMS_LEVELCHANGE	32		// Keep same teams after level change
#define TEAM_NOSPLASH_DAMAGE		64		// Will not inflict rocket splash damage on

#define BOTS_QUAD_RALLY				1		// Quad Rally is ON
#define BOTS_CLASSIC_VOTE			2		// Classic voting is used
#define BOTS_FAIR_TEAMS				4		// Fair teams code is ON
#define BOTS_AUTO_TEAM				8		// Auto select a team for a player is ON
#define BOTS_TEAM_SKINS				16		// Use class/team skins

#define BOTS_NOBODYGUARD			1		// Remove Bodyguard from the server
#define BOTS_NOSNIPER				2		// Remove Sniper from the server
#define BOTS_NOSOLDIER				4		// Remove Soldier from the server
#define BOTS_NOBERZERKER			8		// Remove Berserker from the server
#define BOTS_NOINFILTRATOR			16		// Remove Infiltrator from the server
#define BOTS_NOKAMIKAZEE			32		// Remove Kamikaze from the server
#define BOTS_NONURSE				64		// Remove Nurse from the server
#define BOTS_NOCAPTAIN				128		// Remove Captain from the server
#define BOTS_NOSCIENTIST			256		// Remove Scientist from the server

#define BOTS_CAPTAIN       1
#define BOTS_BODYGUARD     2
#define BOTS_SNIPER        3
#define BOTS_SOLDIER       4
#define BOTS_BERZERKER     5
#define BOTS_INFILTRATOR   6
#define BOTS_KAMIKAZEE     7
#define BOTS_NURSE         8
#define BOTS_SCIENTIST     9

#define	CLASS1	"Captain"
#define	CLASS2	"Bodyguard"
#define	CLASS3	"Sniper"
#define	CLASS4	"Soldier"
#define	CLASS5	"Berzerker"
#define	CLASS6	"Infiltrator"
#define	CLASS7	"Kamikazee"
#define	CLASS8	"Nurse"
#define	CLASS9	"Scientist"

#define SCI_WEAPON_DAMAGE		1
#define SCI_WEAPON_FIRERATE		2
#define SCI_WEAPON_REDUCEDAMMO	3
#define SCI_ARMOR_ADVANCED		4
#define SCI_GENETIC_HEALTH		5
#define SCI_GENETIC_SPEED		6
#define SCI_GENETIC_JUMP		7
#define SCI_GENETIC_STRENGTH	8
#define SCI_GENETIC_STEALTH		9

#define MAX_SCI_UPGRADES		9

typedef struct {
	int 
		levels[MAX_SCI_UPGRADES],	// The tech level
		count;						// current # of ppl playing that class
	float
		values[MAX_SCI_UPGRADES];	// Pre computed values
} bots_sci_class_t;

typedef struct {
	bots_sci_class_t	classes[BOTS_MAX_CLASSES];
	int					timestamp;
} bots_sci_upgrades_t;


typedef struct
{
	int			members;
	int			team_capsinarow;
	int			team_impeachvotes;
	int			team_promos;
	int			team_techpoints;

	bots_sci_upgrades_t sci_upgrades;

	int			nextResearchArea;

	qboolean	hasprotect;

	gentity_t	*cachedCaptain, *cachedScientist; // Updated on every frame
} bots_team_t;

extern bots_team_t	bots_teams[BOTS_MAX_TEAMS];


typedef struct
{
	float		keychecktime;
	float		fairwarning;
	float		startgame;
	int			mapmode;
	int			goalmode;
} bots_info_t;

typedef struct
{
	float		capkeydropped;
	float		techkeydropped;
//	gentity_t	*spawnspot;
//	gentity_t	*keyent;
//	gentity_t	*capkey;
//	gentity_t	*nextrespawn;
//	gentity_t	*lastcapturer;
//	qboolean	isdropped;
//	qboolean	istaken;
//	char		keyname[20];
//	char		flagstart[20];
//	char		flaggoal[20];
//	char		playerstart[30];
//	char		flagstart2[20];
//	char		playerstart2[30];
//	int			keyeffect;
} bots_teamkey_t;

// Prototypes
// spin
qboolean bots_ClientThink_real( gentity_t *ent, usercmd_t *ucmd );
qboolean bots_ConsoleClientCommand( gentity_t *ent, const char *cmd );
qboolean bots_ChangeTeam( gentity_t *ent, char *as_team );
qboolean bots_ChangeClass( gentity_t *ent, int ai_class );
qboolean bots_InitClass( gentity_t *ent );
qboolean bots_GetClientSkin( gentity_t *ent, char *as_model );
qboolean bots_Respawn( gentity_t *ent );
qboolean bots_mapCheck(gentity_t *mapent, gentity_t *player);
void bots_G_SpawnEntitiesFromString( void );
void bots_PlayerDie( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath );
void bots_Coordinates ( gentity_t *ent );
void bots_SpawnGoal( gentity_t *ent );
void bots_SetMaxValues( gentity_t *ent );
void bots_InitTeams();
void bots_ClientConnect( gentity_t *ent );
void bots_initVoting();
int bots_damageLocation (gentity_t *ent, float af_damage);
int bots_CheckArmor (gentity_t *ent, int damage);
int bots_G_LocationDamage(vec3_t point, gentity_t* targ, gentity_t* attacker, int take, int dflags);
float bots_getTechLevel(gentity_t *ent, int ai_upgradeType);
gentity_t *bots_getCaptain (int ai_team);
gentity_t *bots_getScientist (int ai_team);
int bots_getGlobalCount();

void bots_SetSpeed( gentity_t *ent );

void bots_setCaptureCount(int ai_team);
void bots_QuadRally();

void bots_setCaptainLostKey(int ai_team, qboolean ab_clear);
float bots_getCaptainLostKey(int ai_team);
void bots_setScientistLostKey(int ai_team, qboolean ab_clear);
float bots_getScientistLostKey(int ai_team);

void bots_setMode(int ai_mapmode);
int bots_getMode();

void QDECL PrintMsg( gentity_t *ent, const char *fmt, ... );

// nits
void BOTS_Add_Ammo(gentity_t *ent);
qboolean BOTS_ClientCommand(int clientNum);
void BOTS_ClientThink_captain(gentity_t* ent);
void BOTS_ClientThink_bodyguard(gentity_t* ent);
void BOTS_ClientThink_sniper(gentity_t* ent, usercmd_t *ucmd);
void BOTS_ClientThink_soldier(gentity_t* ent);
void BOTS_ClientThink_berzerker(gentity_t* ent);
void BOTS_ClientThink_infiltrator(gentity_t* ent);
void BOTS_ClientThink_kamikazee(gentity_t* ent);
void BOTS_ClientThink_nurse(gentity_t* ent);
void BOTS_ClientThink_scientist(gentity_t* ent);
// csfix: Argh. En sursis
void bots_WriteConfigString(gentity_t* ent);


void BOTS_touch_promo_key(gentity_t* key, gentity_t* ent);
void BOTS_touch_tech_key(gentity_t* key, gentity_t* ent);
void BOTS_set_impeach(gentity_t* ent);
void BOTS_poison_player(gentity_t* ent, qboolean fromWeapon);
void BOTS_ClientDisconnect(gentity_t* ent);
int* BOTS_get_promotech_points(int team);
void BOTS_set_promotech_points(int team, int points[2]);
void BOTS_compute_captain_level(int team);
void BOTS_flashlight(int clientNum);
void BOTS_scientistResearch_setup(int clientNum);
void BOTS_setResearch(int clientNum, char *as_research);
void BOTS_scientistResearchClass_setup(int clientNum);
void BOTS_scientistResearchClass(int clientNum, char *as_class);
void BOTS_proxy_think(gentity_t* self);
qboolean BOTS_nuke_think(gentity_t* self, gentity_t* other);
void BOTS_blind_explode(gentity_t* self);
void BOTS_remove_poison(gentity_t* ent);
void BOTS_explode_nearby_grenades(gentity_t* self);
qboolean BOTS_Pickup_Powerup(gentity_t* ent, int powerup);
qboolean bots_fairTeams (int ai_team);
void BOTS_tech_stripe(int team);

void BOTS_weaponToggle(int clientNum, int classtype);
qboolean BOTS_ClassGeneralCommands(int clientNum, char* cmd);
void BOTS_myclass(int clientNum);
void BOTS_cp_console(int clientNum, char* text);
void BOTS_console(int clientNum, char* text);
gentity_t *bots_getCaptain (int ai_team);
void BOTS_conquer_clear(int team);
void BOTS_conquer_set(int team, int clientNum);
int BOTS_conquer_get(int team);

void BOTS_radio(gentity_t *self, char *arg);

gentity_t *LaunchItem( gitem_t *item, vec3_t origin, vec3_t velocity );
void G_ExplodeMissile( gentity_t *ent );
#define	MISSILE_PRESTEP_TIME	50

// Scoring

#define	BOTS_SCORE_FRAG		0
#define	BOTS_SCORE_POINT	1
#define	BOTS_SCORE_TEAM		2
#define	BOTS_SCORE_ALL		3
#define	BOTS_SCORE_FRAGPT	4
#define	BOTS_SCORE_PENALTY	5
#define	BOTS_SCORE_CAPKILL	6

#define BOTS_FRAG_CAPTAIN_BONUS		5

#define BOTS_PROMOPTS_CAPKILL		1
#define BOTS_PROMOPTS_FLAGCAP		2
#define BOTS_TECHPTS_SCIKILL		1

#define BOTS_GET_PROMOKEY	2
#define BOTS_GET_TECHKEY	1

//void bots_AddScore( gentity_t *ent, int ai_score, int ai_type );
void bots_AddScore( gentity_t *ent, int ai_score, int ai_type, vec3_t origin );
void bots_AddScore_Promo( gentity_t *ent, int ai_score, int ai_type, int ai_promos );
void bots_AddScore_Tech( gentity_t *ent, int ai_tech );
void BOTS_vectorFromAngle(vec3_t forward, vec3_t right, vec3_t up, float angle, vec3_t out);
void BOTS_return_PromoPoints(gentity_t* ent);

#define MAX_MAPDESC			20
#define MAX_MAPFILENAME		12

typedef struct
{
	int		numvotes;
	char	levelname[MAX_MAPDESC];
	char	levelmap[MAX_MAPFILENAME];
} vote_t;

void bots_voteSetup(int clientNum);
void bots_mapVote(int clientNum, char* as_mapname);

qboolean BOTS_shouldFreeze(int selfNum);
qboolean BOTS_toggleFrozenMode(gentity_t *ent);
qboolean BOTS_shouldShuntCommands();

void BOTS_BG_CleanProtect(gentity_t *self);

#endif // __G_BOTS_LOCAL_H__
